package fr.univ.lille1.server.managerimpl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import fr.univ.lille1.server.dao.MessageDao;
import fr.univ.lille1.server.dao.UserDao;
import fr.univ.lille1.server.domain.Message;
import fr.univ.lille1.server.domain.User;
import fr.univ.lille1.server.manager.MessageManager;
import fr.univ.lille1.server.utils.Constants;
import fr.univ.lille1.server.utils.Utils;

@Stateless
public class MessageManagerImpl implements MessageManager {

	@EJB
	private MessageDao messageDao;

	@EJB
	private UserDao userDao;

	@Override
	public Message addMessage(int userId, String title, String content,
			float gpsLat, float gpsLong) {
		if(!Utils.checkString(title) || title.length() > Constants.MAX_CHARACTER_MESSAGE_TITLE){
			return null;
		}
		if(!Utils.checkString(content) || content.length() > Constants.MAX_CHARACTER_MESSAGE_CONTENT){
			return null;
		}
		User user = userDao.find(userId);
		if(!Utils.checkObject(user)){
			return null;
		}
		return messageDao.create(new Message(title, content, gpsLat, gpsLong,
				new Date(), user));
	}

	@Override
	public Message editMessage(int messageId, String content) {
		if(!Utils.checkString(content) || content.length() > Constants.MAX_CHARACTER_MESSAGE_CONTENT){
			return null;
		}
		Message message = messageDao.find(messageId);
		message.setContent(content);
		return messageDao.update(message);
	}

	@Override
	public Message findMessageById(int id) {
		return messageDao.find(id);
	}

	@Override
	public List<Message> findMessagesByLocation(float gpsLat, float gpsLong,
			float range) {
		List<Message> firstList = messageDao.findByLocation(gpsLat, gpsLong,
				range);
		ArrayList<Message> newList = new ArrayList<Message>();
		float dist = 0;
		for (Message m : firstList) {
			dist = calculateDistance(gpsLat, gpsLong, m.getLatitude(),
					m.getLongitude());
			if (dist < range) {
				newList.add(m);
			}
		}
		return newList;
	}

	public static float calculateDistance(float gpsLat1, float gpsLong1,
			float gpsLat2, float gpsLong2) {
		double d2r = Math.PI / 180;
		double distance = 0;

		double dlong = (gpsLong2 - gpsLong1) * d2r;
		double dlat = (gpsLat2 - gpsLat1) * d2r;
		double a = Math.pow(Math.sin(dlat / 2.0), 2) + Math.cos(gpsLat1 * d2r)
				* Math.cos(gpsLat2 * d2r) * Math.pow(Math.sin(dlong / 2.0), 2);
		double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
		distance = 6367 * c;
		// kilometers to meters
		distance *= 1000; 
		return (float) distance;
	}

	@Override
	public Message likeMessage(int id, int userId) {
		Message message = messageDao.find(id);
		User user = userDao.find(userId);
		if(!Utils.checkObject(user)){
			return null;
		}
		message.like(user);
		return messageDao.update(message);
	}

	@Override
	public Message dislikeMessage(int id, int userId) {
		Message message = messageDao.find(id);
		User user = userDao.find(userId);
		if(!Utils.checkObject(user)){
			return null;
		}
		message.dislike(user);
		return messageDao.update(message);
	}

	@Override
	public Message alertMessage(int id, int userId) {
		Message message = messageDao.find(id);
		User user = userDao.find(userId);
		if(!Utils.checkObject(user)){
			return null;
		}
		message.alert(user);
		return messageDao.update(message);
	}

	@Override
	public List<Message> findMessagesByUser(int userId) {
		return messageDao.findByUser(userId);
	}
}
